﻿#if WINDOWS_UWP
#region File and License Information
/*
<File>
	<License>
		Copyright © 2009 - 2017, Daniel Vaughan. All rights reserved.
		This file is part of Calcium (http://calciumsdk.net), 
		which is released under the MIT License.
		See file /Documentation/License.txt for details.
	</License>
	<CreationDate>2013-03-21 20:07:26Z</CreationDate>
</File>
*/
#endregion
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Windows.Foundation.Collections;
using Windows.Storage;
using Outcoder.Data.Serialization;

namespace System.IO.IsolatedStorage
{
	public sealed class IsolatedStorageSettings :
		IDictionary<string, object>, IDictionary,
		ICollection<KeyValuePair<string, object>>, ICollection,
		IEnumerable<KeyValuePair<string, object>>, IEnumerable
	{
		static IsolatedStorageSettings applicationSettings;

		readonly IPropertySet settings = ApplicationData.Current.LocalSettings.Values;

		public bool RaiseExceptionOnDeserializeError { get; set; }

		~IsolatedStorageSettings()
		{
			try
			{
				Save();
			}
			catch (ObjectDisposedException)
			{
				/* Ignore. */
			}
		}

		public static IsolatedStorageSettings ApplicationSettings
		{
			get
			{
				if (applicationSettings == null)
				{
					applicationSettings = new IsolatedStorageSettings();
				}
				return applicationSettings;
			}
		}

		public int Count => settings.Count;

		public ICollection Keys => new List<string>(settings.Keys);

		public ICollection Values
		{
			get
			{
				return new List<object>(settings.Values);
			}
		}

		public object this[string key]
		{
			get
			{
				return settings[key];
			}
			set
			{
				settings[key] = value;
			}
		}

		public void Add(string key, object value)
		{
			settings.Add(key, value);
		}

		public void Clear()
		{
			settings.Clear();
		}

		public bool Contains(string key)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}

			return settings.ContainsKey(key);
		}

		public bool Remove(string key)
		{
			return settings.Remove(key);
		}

		public void Save()
		{
			/* Nothing to do as LocalSettings are managed externally. */
		}

		public bool TryGetValue<T>(string key, out T value)
		{
			object settingsValue;
			if (!settings.TryGetValue(key, out settingsValue))
			{
				value = default(T);
				return false;
			}
			value = (T)settingsValue;
			return true;
		}

		int ICollection<KeyValuePair<string, object>>.Count
		{
			get
			{
				return settings.Count;
			}
		}

		bool ICollection<KeyValuePair<string, object>>.IsReadOnly
		{
			get
			{
				return false;
			}
		}

		void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item)
		{
			settings.Add(item.Key, item.Value);
		}

		void ICollection<KeyValuePair<string, object>>.Clear()
		{
			settings.Clear();
		}

		bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
		{
			return settings.ContainsKey(item.Key);
		}

		void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
		{
			settings.CopyTo(array, arrayIndex);
		}

		bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item)
		{
			return settings.Remove(item.Key);
		}

		ICollection<string> IDictionary<string, object>.Keys
		{
			get
			{
				return settings.Keys;
			}
		}

		ICollection<object> IDictionary<string, object>.Values
		{
			get
			{
				return settings.Values;
			}
		}

		bool IDictionary<string, object>.ContainsKey(string key)
		{
			return settings.ContainsKey(key);
		}

		bool IDictionary<string, object>.TryGetValue(string key, out object value)
		{
			return settings.TryGetValue(key, out value);
		}

		string ExtractKey(object key)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			return (key as string);
		}

		void IDictionary.Add(object key, object value)
		{
			string extractedKey = ExtractKey(key);
			if (extractedKey == null)
			{
				throw new ArgumentException("key");
			}

			settings.Add(extractedKey, value);
		}

		void IDictionary.Clear()
		{
			settings.Clear();
		}

		bool IDictionary.Contains(object key)
		{
			string skey = ExtractKey(key);
			if (skey == null)
			{
				return false;
			}
			return settings.ContainsKey(skey);
		}

		object IDictionary.this[object key]
		{
			get
			{
				string extractedKey = ExtractKey(key);
				return (extractedKey == null) ? null : settings[extractedKey];
			}
			set
			{
				string extractedKey = ExtractKey(key);
				if (extractedKey == null)
				{
					throw new ArgumentException("key");
				}
				settings[extractedKey] = value;
			}
		}

		bool IDictionary.IsFixedSize
		{
			get
			{
				return false;
			}
		}

		bool IDictionary.IsReadOnly
		{
			get
			{
				return false;
			}
		}

		void IDictionary.Remove(object key)
		{
			string extractedKey = ExtractKey(key);
			if (extractedKey != null)
			{
				settings.Remove(extractedKey);
			}
		}

		void ICollection.CopyTo(Array array, int index)
		{
			((ICollection)settings).CopyTo(array, index);
		}

		bool ICollection.IsSynchronized
		{
			get
			{
				return ((ICollection)settings).IsSynchronized;
			}
		}

		object ICollection.SyncRoot
		{
			get
			{
				return ((ICollection)settings).SyncRoot;
			}
		}

		IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
		{
			return settings.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return settings.GetEnumerator();
		}

		IDictionaryEnumerator IDictionary.GetEnumerator()
		{
			var dictionary = new Dictionary<object, object>();
			foreach (var setting in settings)
			{
				dictionary[setting.Key] = setting.Value;
			}
			
			return dictionary.GetEnumerator();
		}
	}
}
#endif